package com.example.actflow.repository;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;

import com.example.actflow.model.AppInfo;
import com.example.actflow.model.Appconfig;
import com.example.actflow.model.LogicItem;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

import java.io.*;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class ContextData {

    @SuppressLint("StaticFieldLeak")
    private static ContextData instance;
    private List<AppInfo> appInfoList;
    private final List<Appconfig> appConfigs = new ArrayList<>();

    private LogicItem root = new LogicItem(LogicItem.Type.CONDITION, "根节点", null);
    private List<LogicItem> currentList = root.children;

    public AppInfo selectedAppInfo;
    private static final String CONFIG_FILE_NAME = "app_configs.json";
    private static final String FLOW_DIR = "flow";

    private final Gson gson = new GsonBuilder()
            .setPrettyPrinting()
            .serializeNulls()
            .disableHtmlEscaping()
            .create();

    private final Context context;

    public static synchronized ContextData getInstance(Context context) {
        if (instance == null) {
            instance = new ContextData(context.getApplicationContext());
        }
        return instance;
    }

    public ContextData(Context context) {
        this.context = context;
        loadAppConfigsFromFile();
    }

    public List<Appconfig> getAppConfigs() {
        return new ArrayList<>(appConfigs); // 返回防御性副本
    }

    public String[] getAppPackageName(){
        return appConfigs.stream()
                .map(a -> a.appInfo.packageName)
                .toArray(String[]::new);
    }

    public void addAppConfig(Appconfig appconfig) {
        appConfigs.add(appconfig);
        saveAppConfigsToFile();
    }

    public void removeAppConfig(String packageName) {
        appConfigs.removeIf(config -> packageName.equals(config.appInfo.packageName));
        saveAppConfigsToFile();
        removeConfigForApp(packageName);
        if(selectedAppInfo.packageName.equals(packageName)){
            selectedAppInfo = null;
        }
    }

    public void setEnable(String packageName,boolean status){
        Optional<Appconfig> first = getAppConfigs().stream().filter(d -> d.appInfo.packageName.equals(packageName)).findFirst();
        if(first.isPresent()){
            first.get().isEnable = status;
            saveAppConfigsToFile();

        }
    }
    public List<AppInfo> getAllInstalledAppInfo() {
        if (appInfoList == null) {
            PackageManager pm = context.getPackageManager();
            List<ApplicationInfo> apps = pm.getInstalledApplications(PackageManager.GET_META_DATA);
            appInfoList = new ArrayList<>();
            for (ApplicationInfo appInfo : apps) {
                String packageName = appInfo.packageName;
                String appName = pm.getApplicationLabel(appInfo).toString();
                appInfoList.add(new AppInfo(packageName, appName));
            }
        }
        return appInfoList;
    }

    private void saveAppConfigsToFile() {
        File file = new File(context.getFilesDir(), CONFIG_FILE_NAME);
        try (Writer writer = new OutputStreamWriter(
                new FileOutputStream(file), StandardCharsets.UTF_8)) {
            gson.toJson(appConfigs, writer);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void loadAppConfigsFromFile() {
        File file = new File(context.getFilesDir(), CONFIG_FILE_NAME);
        if (!file.exists()) return;

        try (Reader reader = new InputStreamReader(
                new FileInputStream(file), StandardCharsets.UTF_8)) {
            Type listType = new TypeToken<List<Appconfig>>() {}.getType();
            List<Appconfig> loadedConfigs = gson.fromJson(reader, listType);

            if (loadedConfigs != null) {
                appConfigs.clear();
                appConfigs.addAll(loadedConfigs);
                if(!appConfigs.isEmpty()){
                    selectedAppInfo = appConfigs.get(0).appInfo;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void saveConfigForApp() {
        if(selectedAppInfo!=null){
            File dir = new File(context.getFilesDir(), FLOW_DIR);
            if (!dir.exists() && !dir.mkdirs()) {
                return;
            }

            File configFile = new File(dir, selectedAppInfo.packageName + ".json");
            try (Writer writer = new OutputStreamWriter(
                    new FileOutputStream(configFile), StandardCharsets.UTF_8)) {
                gson.toJson(root, writer);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public LogicItem loadConfigForApp(String packageName) {
        File configFile = new File(context.getFilesDir(),
                FLOW_DIR + File.separator + packageName + ".json");

        if (!configFile.exists()) {
            return new LogicItem(LogicItem.Type.CONDITION, "根节点", null);
        }

        try (Reader reader = new InputStreamReader(
                new FileInputStream(configFile), StandardCharsets.UTF_8)) {
            return gson.fromJson(reader, LogicItem.class);
        } catch (IOException e) {
            e.printStackTrace();
            return new LogicItem(LogicItem.Type.CONDITION, "根节点", null);
        }
    }

    public void removeConfigForApp(String packageName){
        File configFile = new File(context.getFilesDir(),
                FLOW_DIR + File.separator + packageName + ".json");
        if (configFile.exists()) {
            try {
                configFile.delete();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    public LogicItem getRoot() {
        return root;
    }


    public void setRoot(LogicItem root) {
        this.root = root;
        this.currentList = root.children;
    }

    public List<LogicItem> getCurrentList() {
        return currentList;
    }

    public void setCurrentList(List<LogicItem> currentList) {
        this.currentList = currentList;
    }

    public boolean isEnable(String pkgName) {
        return appConfigs.stream().anyMatch(a-> a.appInfo.packageName.equals(pkgName) && a.isEnable);
    }

    public void clearRoot() {
        setRoot(new LogicItem(LogicItem.Type.CONDITION, "根节点", null));
    }

    public void loadPackage(AppInfo appInfo) {
        selectedAppInfo = appInfo;
        setRoot(loadConfigForApp(appInfo.packageName));
    }
}